package com.aube.base.card;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.aube.base.controller.CardsController;
import com.aube.base.model.OptionItem;
import com.aube.base.model.ReportResultModel;
import com.aube.base.model.TimeLinePiece;
import com.aube.interact.base.R;
import com.aube.base.controller.DataManager;
import com.huyn.baseframework.dynamicload.video.model.GoodsItem;
import com.huyn.baseframework.model.ChannelDetail;
import com.huyn.baseframework.net.BFJSONRequest;
import com.huyn.baseframework.net.HttpRequestLoader;
import com.huyn.baseframework.net.OpenApi;
import com.huyn.baseframework.statistics.AubeStatisticEvents;
import com.huyn.baseframework.statistics.AubeStatisticTool;
import com.huyn.baseframework.statistics.EventValuePair;
import com.huyn.baseframework.utils.StringUtils;
import com.huyn.baseframework.utils.SysUtil;
import com.huyn.baseframework.utils.Utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by hill on 10/24.
 */
public abstract class BaseCardNew extends LinearLayout implements CardsController.IDataSyncHelper {
    private static final String TAG = "Aube/BaseCardNew";

    protected static final String TYPE_INFO = "INFO";
    protected static final String TYPE_QA = "QA";
    protected static final String TYPE_VOTE = "VOTE";
    protected static final String TYPE_PK = "PK";
    protected static final String TYPE_GUESS = "GUESS";

    /**
     * 数据、逻辑变量
     */
    protected Context mContext;

    protected IDataSyncSender iSender;
    protected TimeLinePiece mData;
    protected ChannelDetail mChannelDetail;

    public enum ACTION {SELECTED, CANCELLED, NO_ACTION};

    protected float indexX=-1, indexY=-1;
    protected int mContentHeight = 0;
    protected int mMinHeight = 0;
    protected int mScreenWidth, mScreenHeight;

    /**
     * 各卡片相同元素
     */
    protected FrameLayout mRoot;
    protected LinearLayout mOptionGp;
    protected Drawable mFoldDrawable;
    protected TextView mTitleText, mFoldText, mParticipantsText;
    protected View mDivisionView, mCloseView, mBetterCloseView;

    protected boolean mBExpanded = false;
    protected boolean mBAnimating = false;
    protected boolean mBPreloadDataLoaded = false;
    protected boolean mBDismissed = false;

    protected int BasicMargin, GapMargin;
    protected int mOptionViewHeight, mOptionLineHeight, mRootHeight, mRootWidth;
    protected int mDivisionViewTop, mOptionGpTop;
    protected int mAnimHeight;
    protected int mDivisionViewHeight;
    protected int mOptionGpWidth, mOptionGpHeight;

    protected Animation mVoteAnimation, mVoteExAnimation;

    public BaseCardNew(Context context) {
        this(context, null);
    }
    public BaseCardNew(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public BaseCardNew(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.mContext = context;

        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //do nothing
            }
        });

        mScreenWidth = SysUtil.getAbsoluteScreenWidth(context);
        mScreenHeight = SysUtil.getAbsoluteScreenHeight(context);
    }

    public void init(TimeLinePiece data, ChannelDetail channelDetail) {
        this.mData = data;
        this.mChannelDetail = channelDetail;
    }

    protected void initView() {
        BasicMargin = Utils.dip2px(mContext, 15);
        GapMargin = Utils.dip2px(mContext, 10);
        mDivisionViewHeight = Utils.dip2px(mContext, 5);

        mVoteAnimation = AnimationUtils.loadAnimation(mContext, R.anim.vote_option);

        // Note: set up drawable here
        int cardPosition = mData.getRelativePosition();
        if(cardPosition == 5 || cardPosition == 6 || cardPosition == 7) {  // 5.6.7 - card located in bottom
            mFoldDrawable = getResources().getDrawable(R.drawable.icon_arrowdown);
        } else {
            mFoldDrawable = getResources().getDrawable(R.drawable.icon_arrowup);
        }
        mFoldDrawable.setBounds(0, 0, mFoldDrawable.getMinimumWidth(), mFoldDrawable.getMinimumHeight());

        mFoldText.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                switchFoldLayout();
            }
        });

        mCloseView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Utils.Log(Utils.LogType.DEBUG, TAG, "mCloseView onClick");
                dismiss();
            }
        });

        mBetterCloseView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Utils.Log(Utils.LogType.DEBUG, TAG, "mBetterCloseView onClick");
                dismiss();
            }
        });

        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                switchFoldLayout();
            }
        });

        setupFoldLayout();
    }

    /**
     * 卡片消失. 只设置成View.GONE.
     */
    protected void dismiss() {
        Utils.Log(TAG, "dismiss");
        Animation alphaOutAnim = AnimationUtils.loadAnimation(getContext(), mDismissAnim);
        startAnimation(alphaOutAnim);
        setVisibility(GONE);
        mBDismissed = true;
    }

    /**
     * 根据卡片是否展开设置初始的布局
     */
    protected void setupFoldLayout() {
        Utils.Log(Utils.LogType.DEBUG, TAG, "setupFoldLayout");

        boolean bFold = mData.isCardFold();
        if(bFold) {
            mBExpanded = false;
            mDivisionView.setVisibility(VISIBLE);
            mOptionGp.setVisibility(GONE);
            mFoldText.setText("点击展开");
            mFoldText.setCompoundDrawables(null, null, null, null);
        } else {
            mBExpanded = true;
            mDivisionView.setVisibility(GONE);
            mOptionGp.setVisibility(VISIBLE);
            mFoldText.setText("收起 ");
            mFoldText.setCompoundDrawables(null, null, mFoldDrawable, null);
        }

        Utils.Log(Utils.LogType.DEBUG, TAG, "setupFoldLayout done");
    }

    /**
     * 切换展开/收起布局
     */
    protected void switchFoldLayout() {
        if(mBExpanded) {
            mFoldText.setText("点击展开");
            mFoldText.setCompoundDrawables(null, null, null, null);
            mFoldText.setAlpha(0);
            startCollapseAnim();
        } else {
            mBExpanded = true;
            mFoldText.setText("收起 ");
            mFoldText.setCompoundDrawables(null, null, mFoldDrawable, null);
            mFoldText.setAlpha(0);
            mOptionGp.setVisibility(View.VISIBLE);
            mDivisionView.setVisibility(View.GONE);
            startExpandAnim();

            //统计展开卡片事件
            AubeStatisticTool.getInstance(getContext()).report(AubeStatisticEvents.INTERACT_EXPAND,
                    AubeStatisticEvents.formatValues(new EventValuePair("vid", ""), new EventValuePair("rid", mData.getRid()), new EventValuePair("type", mData.type)));
        }
    }

    public abstract String getType();

    /**
     * TODO 需要考虑到卡片是否超出屏幕
     */
    public void updatePosition() {
        if(mData != null) {
            float[] indexes = mData.getCardIndex();
            indexX = indexes[0];
            indexY = indexes[1];

            if(indexX >=0)
                setTranslationX(mScreenWidth*indexX);
            if(indexY >=0)
                setTranslationY(mScreenHeight*indexY);
        }
    }

    private int mInAnim = R.anim.fade_in;
    private int mDismissAnim = R.anim.fade_out;
    private void generateAnim() {
        String animation = mData.getAnimEffects();
        if(StringUtils.isNotBlank(animation)) {
            try {
                int animStyle = Integer.parseInt(animation);
                switch (animStyle) {
                    case 1:
                        mInAnim = R.anim.push_top_in;
                        mDismissAnim = R.anim.dismiss_top_out;
                        return;
                    case 2:
                        mInAnim = R.anim.push_bottom_in;
                        mDismissAnim = R.anim.dismiss_bottom_out;
                        return;
                    case 3:
                        mInAnim = R.anim.push_left_in;
                        mDismissAnim = R.anim.dismiss_left_out;
                        return;
                    case 4:
                        mInAnim = R.anim.push_right_in;
                        mDismissAnim = R.anim.dismiss_right_out;
                        return;
                    case 5:
                        mInAnim = R.anim.push_left_top_in;
                        mDismissAnim = R.anim.dismiss_left_top_out;
                        return;
                    case 6:
                        mInAnim = R.anim.push_right_top_in;
                        mDismissAnim = R.anim.dismiss_right_top_out;
                        return;
                    case 7:
                        mInAnim = R.anim.push_left_bottom_in;
                        mDismissAnim = R.anim.dismiss_left_bottom_out;
                        return;
                    case 8:
                        mInAnim = R.anim.push_right_bottom_in;
                        mDismissAnim = R.anim.dismiss_right_bottom_out;
                        return;

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void animIn(RelativeLayout parent, Animation.AnimationListener listener) {
        Utils.Log(TAG, "animIn : position = " + mData.getRelativePosition() + ", anim = " + mData.getAnimEffects());
        int relativePisition = mData.getRelativePosition();
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        if(relativePisition >= 0) {
            ViewGenerator.generateParamsStyle(params, relativePisition);
        } else {
            //absolute position
            updatePosition();
        }

        parent.addView(this, params);

        generateAnim();

        Animation anim = AnimationUtils.loadAnimation(getContext(), mInAnim);
        anim.setAnimationListener(listener);
        startAnimation(anim);
    }

    public void animOut(Animation.AnimationListener listener) {
        // temporary fix. confused by current design.
        if(mBDismissed) {
            listener.onAnimationEnd(null);
        } else {
            Animation anim = AnimationUtils.loadAnimation(getContext(), mDismissAnim);
            anim.setAnimationListener(listener);
            startAnimation(anim);
        }
    }

    public void updateCountDown(String time) {

    }

    public void setupSender(IDataSyncSender iSender) {
        this.iSender = iSender;
        doNext();
    }

    public void doNext() {}

    public interface IDataSyncSender {
        public void startSync(String id, boolean oneTime);
        public void postResult(String id, List<OptionItem> results, String cancelId, String selectedId);
        public void close();
        public void onAddRewardGoods(List<GoodsItem> data);
    }

    public void removeSender() {
        iSender = null;
    }

    public void report(String rid, String msg, List<GoodsItem> goodsItemList) {

    }

    public void report(final String rid, final String optionId, final String cancelId, final boolean reportResult) {
        HashMap<String, String> parameterMap = new HashMap<String, String>();
        parameterMap.put("rid", rid);
        if(StringUtils.isNotBlank(cancelId))
            parameterMap.put("cancelOpId", cancelId);
        if(StringUtils.isNotBlank(optionId) && !optionId.equalsIgnoreCase(cancelId))
            parameterMap.put("optionId", optionId);
        parameterMap.put("type", getType());

        //保存
        DataManager.getInstance(getContext()).updateSelectedOptionId(rid, optionId);

        parameterMap.put(OpenApi.API_METHOD, OpenApi.REPORT_DATA);
        BFJSONRequest request = new BFJSONRequest(ReportResultModel.class, parameterMap, new Response.Listener<ReportResultModel>() {

            @Override
            public void onResponse(ReportResultModel response) {
                if(response != null && response.success()) {
                    report(optionId, response.getMessage(), response.getGoodsList());

                    if (reportResult && iSender != null) {
                        iSender.postResult(rid, response.getOptions(), cancelId, optionId);
                    }
                }
            }

            @Override
            public void onErrorResponse(VolleyError error) {
            }

            @Override
            public void onStart() {
            }
        });
        HttpRequestLoader.getInstance(getContext()).startCacheLoader("", request, true);
    }

    protected void reportOptionSelectEvent(EventValuePair data) {
        AubeStatisticTool.getInstance(getContext()).report(AubeStatisticEvents.INTERACT_OPTION_SELECT,
                AubeStatisticEvents.formatValues(new EventValuePair("vid", ""), new EventValuePair("rid", mData.getRid()), new EventValuePair("type", mData.type), data));
    }

    protected void reportOptionSelectEvent(String key, String value) {
        reportOptionSelectEvent(new EventValuePair(key, value));
    }

    private static final int DURATION = 200;
    protected void animGroup(final boolean expand, final View mGroup) {
        float startValue = expand ? mMinHeight : mContentHeight;
        float endValue = expand ? mContentHeight : mMinHeight;
        final ValueAnimator anim = ValueAnimator.ofFloat(startValue, endValue);
        anim.setDuration(DURATION);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();

                LayoutParams params = (LayoutParams) mGroup.getLayoutParams();
                params.height = (int) value;
                mGroup.setLayoutParams(params);
            }
        });
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                if (expand) {
                    mGroup.setAlpha(0);
                    mGroup.setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (!expand)
                    mGroup.setVisibility(View.GONE);
            }
        });

        AnimatorSet set = new AnimatorSet();
        Animator alphaAnim = ObjectAnimator.ofFloat(mGroup, "alpha", expand ? 0 : 1, expand ? 1 : 0);
        alphaAnim.setDuration(DURATION);

        if(expand) {
            set.playSequentially(anim, alphaAnim);
        } else {
            set.playSequentially(alphaAnim, anim);
        }
        set.start();
    }

    public void reSortData(HashMap<String, Float> mSet) {
        String maxId="";
        float max = 0;
        float total = 0;
        Iterator<Map.Entry<String, Float>> iterator = mSet.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Float> entry = iterator.next();
            total += entry.getValue();
            if(entry.getValue() > max) {
                max = entry.getValue();
                maxId = entry.getKey();
            }
        }

        if(total > 100) {
            float value = mSet.get(maxId);
            mSet.put(maxId, value + 100 - total);
        }
    }

    public void onCardInAnimEndEvent() {
        if(!mData.isCardFold()) {
            // load preset data if not fold default
            if(!mBPreloadDataLoaded)
                loadPresetData();
        }
    }

    protected void loadPresetData() {
    }

    /**
     * 卡片展开动画
     */
    protected void startExpandAnim() {
        Utils.Log(Utils.LogType.DEBUG, TAG, "startExpandAnim");

        mBAnimating = true;

        final float oriHeight = mRoot.getHeight();
        final float targetHeight = BasicMargin + mTitleText.getMeasuredHeight() + GapMargin + mOptionViewHeight * mData.optionSize() + mParticipantsText.getMeasuredHeight();

        final ValueAnimator anim = ValueAnimator.ofFloat(0.0f, 1.0f);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animValue = (float) animation.getAnimatedValue();

                LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mRoot.getLayoutParams();
                params.height = mAnimHeight = (int) (oriHeight + (targetHeight - oriHeight) * animValue);

                mRoot.setLayoutParams(params);
                mFoldText.setAlpha(animValue);
                mOptionGp.setAlpha(animValue);
            }
        });

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mBAnimating = false;
                mBExpanded = true;

                // load preset data if not fold default
                if(!mBPreloadDataLoaded)
                    loadPresetData();
            }
        });

        anim.setDuration(400);
        anim.setTarget(mRoot);
        anim.start();

        Utils.Log(Utils.LogType.DEBUG, TAG, "startExpandAnim done");
    }

    /**
     * 卡片收起动画
     */
    protected void startCollapseAnim() {
        Utils.Log(Utils.LogType.DEBUG, TAG, "startCollapseAnim");

        mBAnimating = true;

        final float oriHeight = mRoot.getHeight();
        final float targHeight = BasicMargin + mTitleText.getMeasuredHeight() + GapMargin + mOptionLineHeight + mParticipantsText.getMeasuredHeight();

        final ValueAnimator anim = ValueAnimator.ofFloat(0.0f, 1.0f);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animValue = (float) animation.getAnimatedValue();

                LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mRoot.getLayoutParams();
                params.height = mAnimHeight = (int) (oriHeight - (oriHeight - targHeight) * animValue);

                mRoot.setLayoutParams(params);
                mFoldText.setAlpha(animValue);
                mRoot.requestLayout();

                mOptionGp.setAlpha(1 - animValue);
            }
        });

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mBAnimating = false;
                mBExpanded = false;
                mOptionGp.setVisibility(View.GONE);
                mDivisionView.setVisibility(View.VISIBLE);
            }
        });

        anim.setDuration(400);
        anim.setTarget(mRoot);
        anim.start();

        Utils.Log(Utils.LogType.DEBUG, TAG, "startCollapseAnim done");
    }

    /**
     * 百分比样式格式化, %小于数字大小
     * @param value
     * @return
     */
    protected String doPercentHtmlFormat(int value) {
        return String.valueOf(value) + "<font><small>%</small></font>";
    }
}
